home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 019 / see123.pas < prev    next >
Pascal/Delphi Source File  |  1986-09-24  |  21KB  |  635 lines

  1. Program LotusLOOK; (* A Program to read and partially decode LOTUS123 files *)
  2.  
  3. (*
  4.   The purpose of this example program is to provide the information needed
  5.   to create and interpret 1-2-3 data files from within a Turbo Pascal
  6.   program.
  7.  
  8.   This file contains the type definitions and procedures necessary to read
  9.   and write Lotus 1-2-3 WKS files. The program will work with versions
  10.   1,1a and 2 of 1-2-3.
  11.  
  12.   The information in this program was developed from two sources; First,
  13.   a handout which was distributed at the Lotus Developer's conference
  14.   held by Lotus, and second, plain old trial and error. The information
  15.   distributed at the conference gave the name of each type of record
  16.   and the number of bytes normally contained by that record. Trial and
  17.   error was used to determine how the information in the records was to
  18.   be interpreted. In the case of some record types, no attempt has been
  19.   made to interpret the data. For instance, the definition of graph
  20.   records has been defined as an array of bytes without regard for
  21.   the actual function of those bytes.
  22.  
  23.   A Lotus 1-2-3 File consists of a series of variable length records.
  24.   The first two bytes of each record represent an integer which gives
  25.   the record Type, the third and fourth bytes contain an integer which
  26.   represents the number of bytes in the record (exclusive of the type
  27.   and length bytes).
  28.  
  29.   Columns and Rows within the worksheet are numbered starting with 0.
  30.   Thus, cell A1 in the spreadsheet is Cell[0,0] in the matrix, cell B2
  31.   is Cell[1,0]. Cells are written to the file in sequence working across
  32.   each row, i.e., all the cells in row 0 are written, then all cells in
  33.   row 1, etc.
  34.  
  35.   Each record describing a cell contains a format byte, the column and
  36.   row where it fits in the matrix and the contents of that cell, be it
  37.   integer, floating point, text, or fomula. Cells containing dates
  38.   are treated as integer cells. Text information is stored in the form
  39.   of ASCII Z strings. Unlike Turbo strings where byte[0] gives the length
  40.   of the string, ASCIIZ strings are arrays of characters with a character
  41.   #0 representing the end of the string. The format byte consists of two
  42.   4 bit fields, one of which is used to flag the format type--Fixed, Currency,
  43.   Date, etc.  The other is used to denote the decimal places to be used, or
  44.   the number of the date type. Experiment with files of your own creation,
  45.   and you will be able to see the relationships.
  46.  
  47.   The basic 1-2-3 record types are:
  48.  
  49.   0 : Beginning of File - 2 Data Bytes;
  50.   1 : End of File - 0 Data Bytes;
  51.   2 : Method of Calculation - 1 Data Byte;
  52.   3 : Calculation order - 1 Data Byte;
  53.   4 : Window Split Indicator - 1 Data Byte;
  54.   5 : Window Synchronization Indicator - 1 Data Byte;
  55.   6 : WorkSheet Dimensions - Number of Columns, Number of Rows : Integers;
  56.  *7 : First Window Data - Varies depending on version number
  57.   8 : Column width overrides - Column number, Column width;
  58.       A column width record exists for any column for which the
  59.       user has established a width other than the default;
  60.  *9 : Second Window Data - Varies depending on version number;
  61.   10 : Column Width Overrides for window two;
  62.   11 : Named Range : Title, Column,Row of upper corner, Column,Row of lower
  63.        corner;
  64.   12 : Blank Cell : Format Byte, Column, Row; A cell with no contents
  65.   13 : Integer Cell : Format Byte, Column, Row, cell contents;
  66.   14 : Floating Point Cell : Format Byte, Column, Row, IEEE Real Number;
  67.   15 : Label Cell : Format Byte, Column, Row, Contents
  68.   16 : Formula Cell : Format Byte, Column, Row, Contents
  69.  *24 : Data Table Range : 25 Bytes representing the coordinates of the range;
  70.  *25 : Query Range : 25 bytes representing the coordinate;
  71.  *26 : Print Range : Column and row of the upper and lower corners of the range
  72.  *27 : Sort Range : Column and row of the upper and lower corners of the range
  73.  *28 : Fill Range : Column and row of the upper and lower corners of the range
  74.  *29 : Primary Sort Key : Coordinates of top and bottom of the range,
  75.        Byte denoting ascending or descending sort
  76.  *32 : Distribution range : Coordinates of the range;
  77.  *35 : Secondary Sort Key : Coordinates of top and bottom of the range,
  78.        Byte denoting ascending or descending sort
  79.   36 : Global Protection : Byte
  80.   37 : Footer : ASCII Z string for page footer;
  81.   38 : Header : ASCII Z string for page header;
  82.   39 : Setup String : ASCII Z string for printer setup;
  83.  *40 : Print Margins : Left, Rigth Margin, Page Length, Top , Bottom Margin
  84.   41 : Global Label Alignment Character : Character (',",^);
  85.  *42 : Borders : Coordinates of print borders;
  86.  *45 : Current Graph Information : 437 Bytes;
  87.  *46 : Named Graph Information : 453 Bytes;
  88.   47 : Iteration Count : Byte;
  89.   48 : Print Format Flag : Byte;
  90.   49 : Active Window Flag : Byte;
  91.  
  92.   * denotes definitions where the ordering of information has not yet been
  93.     established.
  94.  
  95. An "Empty File" (No data in the cells yet) as created by Lotus 1-2-3
  96. contains the following records:
  97.  
  98.    0 - Begin File Information
  99.    6 - Spreadsheet Dimensions
  100.   47 - Iteration setting
  101.    2 - Calculation method
  102.    3 - Calculation order
  103.    4 - Split Window Flag
  104.    5 - Window Synchronization Flag
  105.    7 - Window 1 Data
  106.   24 - Data Table information
  107.   25 - Query Range information
  108.   26 - Print Range information
  109.   48 - Print format flag
  110.   28 - Data Fill range information
  111.   27 - Data Sort Range information
  112.   29 - Primary Sort Range
  113.   35 - Secondary Sort Range
  114.   32 - Distribution Range
  115.   36 - Protection Flag
  116.   37 - Footer
  117.   38 - Header
  118.   39 - Setup string
  119.   40 - Margins
  120.   41 - Global label alignment character
  121.   42 - Print borders
  122.   45 - Graph settings
  123.  
  124. Although 1-2-3 places these records in an empty file, my tests have shown that
  125. a file containing just the BeginFile record, the Worksheet Dimensions record,
  126. then the various cells to be placed in the file and then the EndFile record
  127. will be loaded properly by 1-2-3. This appears to offer a more streamlined
  128. method of creating files which can be used by 1-2-3; plus it saves all the
  129. disk file space which is occupied by those default records.
  130.  
  131. It appears that in the various range records the byte 255 is used to indicate
  132. that the range has not yet been set.
  133.  
  134. In order to read a 1-2-3 file, one merely opens the file and starts reading
  135. the record type bytes, after the record type has been read the next two
  136. bytes will tell you how many data bytes there are in the record. Read the
  137. specified number of bytes into a buffer and then apply the proper interp-
  138. retation to those bytes. In order to facilitate this process a Pascal
  139. record with variant parts has been defined.
  140.  
  141. The primary need of a Turbo programmer will be to transfer a data base
  142. or other data from a Turbo application to a 1-2-3 application. By writing
  143. directly to a 1-2-3 format file one can spare the user of the program
  144. the burden of dumping the data to a DIF or Text file and then using the
  145. 1-2-3 translate programs to place the data in a 1-2-3 worksheet file which,
  146. by the way, do not behave too well when text and numeric data are mixed.
  147.  
  148. Preparing the Turbo generated 1-2-3 file requires that the file be
  149. filled with the default values for the records found in all files.
  150. Then the actual data base information would be written to the file
  151. one row (record) at a time, making the proper conversions from
  152. Turbo strings and turbo reals. Dates, of course, would have to be
  153. converted to integers if the application will call for manipulation
  154. of the dates within 1-2-3. Several programs in the Borland SIG DL1
  155. contain routines to convert dates to integers based on various starting
  156. dates.
  157.  
  158. Comments, improvements, etc. can be addressed to:
  159.     Gary Macker, CPA
  160.     Compuserve ID 76314,2747
  161.  
  162. *)
  163.  
  164. Type
  165.   String16 = String[16];
  166.  
  167.   ByteFile = File of Byte;
  168.  
  169.   ZType = Array[1..255] of Char; (* ASCII Z String *)
  170.  
  171.   AnyString = String[255];
  172.  
  173.   IEEERealType = Array[1..8] of byte;
  174.  
  175.   TurboRealType = Array[1..6] of byte;
  176.  
  177.   MantissaType = Array[1..5] of byte;
  178.  
  179.   BitType = (B0,B1,B2,B3,B4,B5,B6,B7);
  180.  
  181.   BitSetType = Set of B0..B7;
  182.  
  183.   WksDimType = Record
  184.     UpLftCol : Integer; (* Home *)
  185.     UpLftRow : Integer;
  186.     LowRtCol : Integer; (* End Home *)
  187.     LowRtRow : Integer
  188.   End;
  189.  
  190.   WinDataType = Record
  191.     Col : Integer;
  192.     Width : Byte;
  193.   End;
  194.  
  195.   RangeRecType = Record
  196.     Name : Array[1..16] of Char; (* An ASCIIZ String *)
  197.     Col1,Row1,Col2,Row2 : Integer;
  198.   End;
  199.  
  200.   BlankCellType = Record
  201.     Format : BitSetType;
  202.     Col,Row : Integer;
  203.   End;
  204.  
  205.   IntegerCellType = Record
  206.     Format : BitSetType;
  207.     Col,Row,Num : Integer;
  208.   End;
  209.  
  210.   RealCellType = Record
  211.     Format : BitSetType;
  212.     Col,Row : Integer;
  213.     Num : IEEERealType;
  214.   End;
  215.  
  216.   LabelCellType = Record
  217.     Format : BitSetType;
  218.     Col,Row : Integer;
  219.     CellLabel : ZType;
  220.   End;
  221.  
  222.   FormulaCellType = Record
  223.     Format : BitSetType;
  224.     Col,Row : Integer;
  225.     LastValue : IEEERealType;
  226.     Formula : Array[1..255] of Byte;
  227.   End;
  228.  
  229.   LotusRecType = Record
  230.     RecType : Integer;
  231.     RecSize : Integer;
  232.     Case Integer of
  233.     0 : (Flag1,Flag2 : Byte);
  234.     2 : (CalcMethod : Byte);
  235.     3 : (CalcOrder : Byte);
  236.     4 : (SplitWindow : Byte);
  237.     5 : (WindowSynch : Byte);
  238.     6 : (WksDim : WksDimType);
  239.     7 : (FirstWindowFlags : Array[1..32] of Byte); (* 31 bytes in Ver 1,1A; 32 in Ver 2 *)
  240.     8 : (WinOneData : WinDataType);
  241.     9 : (SecondWindowFlags : Array[1..32] of Byte); (* 31 bytes in Ver 1,1A; 32 in Ver 2 *)
  242.     10 : (WinTwoData : WinDataType);
  243.     11 : (RangeRec : RangeRecType);
  244.     12 : (BlankCell : BlankCellType);
  245.     13 : (IntegerCell : IntegerCellType);
  246.     14 : (RealCell : RealCellType);
  247.     15 : (LabelCell : LabelCellType);
  248.     16 : (FormulaCell : FormulaCellType);
  249.     24 : (TableData : Array[1..25] of Byte);
  250.     25 : (QueryRangeData : Array[1..25] of Byte);
  251.     26 : (PrintRangeCol1,PrintRangeRow1,PrintRangeCol2,PrintRangeRow2 : Integer);
  252.     27 : (SortRangeData : Array[1..4] of Integer);
  253.     28 : (FillRangeData : Array[1..4] of Integer);
  254.     29 : (PrimSortData : Array[1..9] of Byte);
  255.     32 : (DistRangeData : Array[1..16] of Byte);
  256.     35 : (SecSortData : Array[1..9] of Byte);
  257.     36 : (ProtectOn : Byte);
  258.     37 : (Footer : Array[1..242] of Char);
  259.     38 : (Header : Array[1..242] of Char);
  260.     39 : (SetupString : Array[1..40] of Char);
  261.     40 : (LeftM,RightM,PageL,BottM,TopM : Integer);
  262.     41 : (LabelPrefix : Char);
  263.     42 : (BorderRange : Array[1..8] of Integer);
  264.     45 : (GraphData : Array[1..437] of Integer);
  265.     46 : (NamedGraphData : Array[1..453] of Integer);
  266.     47 : (Iteration : Byte);
  267.     48 : (PrintFormat : Byte);
  268.     49 : (ActiveWindow : Byte);
  269.   End;
  270.  
  271. Var
  272.   LotusRec : LotusRecType;
  273.   RecordBuffer : Array[1..455] of Byte Absolute LotusRec;
  274.   F : ByteFile;
  275.   FileName : String[60];
  276.   C,Ch : Char;
  277.  
  278. Const
  279.   RecNames : Array[0..$31] of String[25] = (
  280.   'Begin File',
  281.   'End File',
  282.   'Calculation Method',
  283.   'Calculation Order',
  284.   'Split Window',
  285.   'Window Synch',
  286.   'Worksheet Dimensions',
  287.   'First Window',
  288.   'Col Width Overrides/1',
  289.   'Second Widow',
  290.   'Col Width Overrides/2',
  291.   'Named Range',
  292.   'Blank Cell',
  293.   'Integer Cell',
  294.   'Floating Point Cell',
  295.   'Label Cell',
  296.   'Formula Cell',
  297.   '',
  298.   '',
  299.   '',
  300.   '',
  301.   '',
  302.   '',
  303.   '',
  304.   'Table Range',
  305.   'Query Range',
  306.   'Print Range',
  307.   'Sort Range',
  308.   'Fill Range',
  309.   'Primary Key',
  310.   '',
  311.   '',
  312.   'Distribution Range',
  313.   '',
  314.   '',
  315.   'Secondary Key',
  316.   'Global Protection',
  317.   'Print Footer',
  318.   'Print Header',
  319.   'Setup String',
  320.   'Print Margins',
  321.   'Global Label',
  322.   'Print Borders',
  323.   '',
  324.   '',
  325.   'Current Graph Settings',
  326.   'Named Graph',
  327.   'Iteration Count',
  328.   'Print Format Mode',
  329.   'Active Window');
  330.  
  331.   Zero : Byte = 0;
  332.   One : Byte = 1;
  333.   two : Byte = 2;
  334.   Three : Byte = 3;
  335.   Four : Byte = 4;
  336.   Five : Byte = 5;
  337.   Six : Byte = 6;
  338.   Seven : Byte = 7;
  339.   Eight : Byte = 8;
  340.   Nine : Byte = 9;
  341.   Ten : Byte = 10;
  342.   Eleven : Byte = 11;
  343.   Twelve : Byte = 12;
  344.   Thirteen : Byte = 13;
  345.   Fourteen : Byte = 14;
  346.  
  347. Function IeeeToTurbo(long : IEEERealType) : Real;
  348.  
  349. (*
  350.  * This function was adapted from information supplied by Borland for use
  351.  * in reading and writing Reflex data files. Note that the routine as
  352.  * set forth in that file did not handle the conversion properly when
  353.  * the number was 0.00. It added the bias to the exponent, which then
  354.  * made the converted number non-zero. A zero exponent (absolute zero,
  355.  * not zero after correcting for the sign bit) denotes 0.00 in both
  356.  * the IEEE and Turbo 6 byte formats. A secondary result of the way
  357.  * in which I have altered the routine is that if the exponent falls
  358.  * outside the possible range for a Turbo real, the number will be
  359.  * converted to 0.00. You may want to institute different error
  360.  * handling in your application
  361.  *)
  362.  
  363. Var
  364.   R : Real;
  365.   I : Integer;
  366.   E : byte;
  367.   T : TurboRealType Absolute R;
  368.   Sign : Byte;
  369.  
  370. Begin
  371.   FillChar(R,SizeOf(R),0);
  372.   I := (long[8] and $7f) shl 4;
  373.   I := I or ((long[7] and $f0) shr 4);
  374.   if (I < 985) or (I > 1061) then T[1] := 0
  375.   Else
  376.   Begin
  377.     I := I - 1023;
  378.     T[1] := I + $81;
  379.   End;
  380.   Sign := long[8] and $80;
  381.   T[6] := sign + ((long[7] and $0f) shl 3) or ((long[6] and $e0) shr 5);
  382.   for I := 5 downto 2 do
  383.     t[I] := ((long[I+1] and $1f) shl 3) or ((long[I] and $e0) shr 5);
  384.   If T[1] <> 0 Then IEEEtoTurbo := R Else R := 0;
  385. End;
  386.  
  387. Procedure TurboToIEEE(Var TN : Real; Var IEEE : IEEERealType);
  388. Var
  389.   TR : TurboRealType Absolute TN;
  390.   E : Integer;
  391.   Sign : Byte;
  392. Begin
  393.   FillChar(IEEE,SizeOf(IEEE),0); (* Start with a clean slate *)
  394.   If TR[1] <> 0 Then (* Zero means 0.00 *)
  395.   Begin
  396.     Sign := TR[6] and $80;
  397.     E := TR[1] - $81;
  398.     E := E + 1023;
  399.     IEEE[8] := Sign + (E Shr 4);
  400.     IEEE[7] := E Shl 4;
  401.     TR[6] := TR[6] or $80;
  402.     IEEE[7] := IEEE[7] + ((TR[6] and $78) Shr 3);
  403.     IEEE[6] := ((TR[6] and $07) Shl 5) + ((TR[5] and $F8) Shr 3);
  404.     IEEE[5] := ((TR[5] and $07) Shl 5) + ((TR[4] and $F8) Shr 3);
  405.     IEEE[4] := ((TR[4] and $07) Shl 5) + ((TR[3] and $F8) Shr 3);
  406.     IEEE[3] := ((TR[3] and $07) Shl 5) + ((TR[2] and $F8) Shr 3);
  407.     IEEE[2] := ((TR[2] and $07) Shl 5) + (($0 and $F8) Shr 3);
  408.     IEEE[1] := 0; (* Least significant bits made 0 *)
  409.   End;
  410. End;
  411.  
  412. Procedure GetName;
  413. Var
  414.   I : Integer;
  415. Begin
  416.   ClrScr;
  417.   Write('ENTER THE NAME OF THE FILE YOU WANT TO DECODE :');
  418.   ReadLn(FileName);
  419.   If FileName = '' Then Halt;
  420.   For I := 1 to Length(FileName) Do FileName[I] := UpCase(FileName[I]);
  421.   If Pos('.',FileName) = 0 Then FileName := FileName +'.WKS';
  422. End;
  423.  
  424. Function OpenFile(FN : AnyString) : Boolean;
  425. Var
  426.   B : Boolean;
  427. Begin
  428.   Assign(F,FN);
  429.   {$I-}
  430.   Reset(F);
  431.   B := (IOResult = 0);
  432.   {$I+}
  433.   If Not B Then Close(F);
  434.   OpenFile := B;
  435. End;
  436.  
  437. Procedure ReadLotusRec(Var F : ByteFile); (* Assumes that the file pointer is at the start of a record *)
  438. Var
  439.   I : Integer;
  440. Begin
  441.   For I := 1 to 4 Do Read(F,RecordBuffer[I]);
  442.   For I := 5 to LotusRec.RecSize+4 Do Read(F,RecordBuffer[I]);
  443. End;
  444.  
  445. Procedure WriteZ(Var Z);
  446. Var
  447.   ZString : ZType Absolute Z;
  448.   I : Byte;
  449. Begin
  450.   I := 1;
  451.   While ZString[I] > #0 Do
  452.   Begin
  453.     Write(ZString[I]);
  454.     I := Succ(I);
  455.   End;
  456. End;
  457.  
  458. Function BitRep(B : BitSetType) : String16;
  459. Var
  460.   S : String16;
  461.   Bit : BitType;
  462. Begin
  463.   S := '';
  464.   For Bit := B7 downto B0 Do If Bit in B Then S := S +'1 ' Else S := S + '0 ';
  465.   BitRep := S;
  466. End;
  467.  
  468. Procedure PrintRec;
  469. Var
  470.   I : Integer;
  471.   R : Real;
  472. Begin
  473.   WriteLn('Record Type   = ',LotusRec.RecType,'  ',RecNames[LotusRec.RecType]);
  474.   WriteLn('Size in Bytes = ',LotusRec.RecSize);
  475.   WriteLn('Record Contents:');
  476.   With LotusRec Do Case RecType of
  477.     0 : Write(Flag1:4,Flag2:4);
  478.     1 : Begin End;
  479.     2 : Write(CalcMethod);
  480.     3 : Write(CalcOrder);
  481.     4 : Write(SplitWindow);
  482.     5 : Write(WindowSynch);
  483.     6 : With WksDim Do Begin
  484.          Write(UpLftCol:4, UpLftRow:4, LowRtCol:4, LowRtRow:4);
  485.         End;
  486.     7 : For I := 1 to RecSize Do Write(FirstWindowFlags[I]:4);
  487.     8 : With WinOneData Do Write('Column ',Col,' is ',Width,' Spaces Wide');
  488.     9 : For I := 1 to RecSize Do Write(SecondWindowFlags[I]:4);
  489.     10 : With WinTwoData Do Write('Column ',Col,' is ',Width,' Spaces Wide');
  490.     11 : With RangeRec Do Begin
  491.            WriteZ(Name);
  492.            WriteLn;
  493.            Write('Column 1 ',Col1,' Row 1 ',Row1,' Column 2 ',Col2,' Row 2 ',Row2);
  494.          End;
  495.     12 : With BlankCell Do Begin
  496.            WriteLn('Format Byte = ',BitRep(Format));
  497.            Write('Column ',Col,' Row ',Row);
  498.          End;
  499.     13 : With IntegerCell Do Begin
  500.            WriteLn('Format Byte = ',BitRep(Format));
  501.            WriteLn('Column ',Col,' Row ',Row);
  502.            Write('Integer Value is ',Num);
  503.          End;
  504.     14 : With RealCell Do Begin
  505.            WriteLn('Format Byte = ',BitRep(Format));
  506.            WriteLn('Column ',Col,' Row ',Row);
  507.            R := IEEEtoTurbo(Num);
  508.            Write('Cell Value is ',R:15:2);
  509.          End;
  510.     15 : With LabelCell Do Begin
  511.            WriteLn('Format Byte = ',BitRep(Format));
  512.            WriteLn('Column ',Col,' Row ',Row);
  513.            WriteZ(CellLabel);
  514.         End;
  515.     16 : With FormulaCell Do Begin
  516.            WriteLn(BitRep(Format));
  517.            WriteLn('Column ',Col,' Row ',Row);
  518.            I := 1;
  519.            R := IEEEtoTurbo(LastValue);
  520.            WriteLn('Last Computed Value is ',R:15:2);
  521.            For I := 1 to (LotusRec.RecSize - 8) Do Write(Formula[I]:4);
  522.          End;
  523.     24 : For I := 1 to RecSize Do Write(TableData[I]:4);
  524.     25 : For I := 1 to RecSize Do Write(QueryRangeData[I]:4);
  525.     26 : Write(PrintRangeCol1:4,PrintRangeRow1:4,PrintRangeCol2:4,PrintRangeRow2:4);
  526.     27 : For I := 1 to 4 Do Write(SortRangeData[I]:4);
  527.     28 : For I := 1 to 8 Do Write(FillRangeData[I]:4);
  528.     29 : For I := 1 to RecSize Do Write(PrimSortData[I]:4);
  529.     32 : For I := 1 to RecSize Do Write(DistRangeData[I]:4);
  530.     35 : For I := 1 to 9 Do Write(SecSortData[I]:4);
  531.     36 : Write(ProtectOn);
  532.     37 : WriteZ(Footer);
  533.     38 : WriteZ(Header);
  534.     39 : WriteZ(SetupString);
  535.     40 : Write('Left ',LeftM,' Right ',RightM,' Top ',TopM,' Bottom ',BottM,' Page Length ',PageL);
  536.     41 : Write(LabelPrefix);
  537.     42 : For I := 1 to 8 Do Write(BorderRange[I]:4);
  538.     45 : For I := 1 to 437 Do Write(GraphData[I]:4);
  539.     46 : For I := 1 to 453 Do Write(NamedGraphData[I]:4);
  540.     47 : Write(Iteration);
  541.     48 : Write(PrintFormat);
  542.     49 : Write(ActiveWindow);
  543.   End;
  544.   WriteLn;
  545. End;
  546.  
  547. Procedure WriteBeginFile(Var F : ByteFile);
  548. Begin
  549.   Write(F,Zero,Zero,Two,Zero,Four,Four);
  550.   (* Record Type 0, Record Size 2, ??? 4, 4 *)
  551. End;
  552.  
  553. Procedure WriteWksSize(Var F : ByteFile; Cols,Rows : Integer);
  554. Var
  555.   B : Byte;
  556. Begin
  557.   Write(F,Six,Zero,Eight,Zero,Zero,Zero,Zero,Zero);
  558.   B := Lo(Cols);
  559.   Write(F,B);
  560.   B := Hi(Cols);
  561.   Write(F,B);
  562.   B := Lo(Rows);
  563.   Write(F,B);
  564.   B := Hi(Rows);
  565.   Write(F,B);
  566. End;
  567.  
  568. Procedure WriteRealCell(Var F : ByteFile; FormatByte : Byte; Col,Row : Integer; Value : Real);
  569. Var
  570.   B : Byte;
  571.   IE : IEEERealType;
  572.  
  573. Begin
  574.   Write(F,Fourteen,Zero,Thirteen,Zero,FormatByte);
  575.   B := Lo(Col);
  576.   Write(F,B);
  577.   B := Hi(Col);
  578.   Write(F,B);
  579.   B := Lo(Row);
  580.   Write(F,B);
  581.   B := Hi(Row);
  582.   Write(F,B);
  583.   TurboToIEEE(Value,LotusRec.RealCell.Num);
  584.   For B := 1 to 8 Do Write(F,LotusRec.RealCell.Num[B]);
  585. End;
  586.  
  587. Procedure WriteIntegerCell(Var F : ByteFile; FormatByte : Byte; Col,Row,Value : Integer);
  588. Var
  589.   B : Byte;
  590. Begin
  591.   Write(F,Thirteen,Zero,Seven,Zero,FormatByte);
  592.   B := Lo(Col);
  593.   Write(F,B);
  594.   B := Hi(Col);
  595.   Write(F,B);
  596.   B := Lo(Row);
  597.   Write(F,B);
  598.   B := Hi(Row);
  599.   Write(F,B);
  600.   B := Lo(Value);
  601.   Write(F,B);
  602.   B := Hi(Value);
  603.   Write(F,B);
  604. End;
  605.  
  606. Procedure EndLotusFile(Var F : ByteFile);
  607. Begin
  608.   Write(F,One,Zero,Zero,Zero);
  609.   Close(F);
  610. End;
  611.  
  612. Begin
  613.   Repeat GetName Until OpenFile(FileName);
  614.   Repeat
  615.     ReadLotusRec(F);
  616.     PrintRec;
  617.     Read(kbd,C);
  618.   Until LotusRec.RecType = 1;
  619.   Close(F);
  620.   Writeln('Create a sample WKS file... ? Y/N');
  621.   Write('It will be called TEST2.WKS');
  622.   Read(Ch);
  623.   If UpCase(CH) = 'Y' Then
  624.   Begin
  625.     Assign(F,'TEST2.WKS');
  626.     ReWrite(F);
  627.     WriteBeginFile(F);
  628.     WriteWksSize(F,2,0);
  629.     WriteIntegerCell(F,255,0,0,1);
  630.     WriteIntegerCell(F,255,1,0,2);
  631.     WriteRealCell(F,255,2,0,1.123);
  632.     EndLotusFile(F);
  633.   End;
  634. End.
  635.